home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue50 / Except / LIUTILS.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-09-03  |  8.4 KB  |  366 lines

  1. unit LIUtils;
  2.  
  3. interface
  4.  
  5. const
  6.   xorMask               = $AA;
  7.   escMask               = $3F;
  8.   escLineShift          = 6;
  9.   escByteLineByteOfs    = $3F;
  10.   escWordLineWordOfs    = $3E;
  11.   escWordLineDWordOfs   = $3C;
  12.   escFileName           = $3B;
  13.   escFirst              = $3B;
  14.  
  15. type
  16.   PByte     = ^Byte;
  17.   PShortInt = ^ShortInt;
  18.   PWord     = ^Word;
  19.   PSmallInt = ^SmallInt;
  20.   PDWord    = ^Longint;
  21.   PLongint  = ^Longint;
  22.  
  23.   PRTLIHeader = ^TRTLIHeader;
  24.   TRTLIHeader = record
  25.     rtliUnitCount: Integer;
  26.     rtliPublicCount: Integer;
  27.     rtliLineCount: Integer;
  28.     rtliFixup: Integer;
  29.   end;
  30.  
  31.   TGrowingArray = class
  32.   protected
  33.     FArrPtr:      Pointer;
  34.     FCurPtr:      Pointer;
  35.     FElementSize: Integer;
  36.     FLimit:       Integer;
  37.     FCount:       Integer;
  38.     FDelta:       Integer;
  39.     procedure SetLimit(NewLimit: Integer);
  40.     function GetItem(Index: Integer): Pointer;
  41.   public
  42.     constructor Create(ALimit,ADelta,AElementSize: Integer);
  43.     destructor Destroy; override;
  44.     function Add: Pointer;
  45.     function Allocate(No: Integer): Pointer;
  46.     property Items[Index: Integer]: Pointer read GetItem; default;
  47.     property ArrPtr: Pointer read FArrPtr;
  48.     property Count: Integer read FCount;
  49.     property Limit: Integer read FLimit write SetLimit;
  50.     property ElementSize: Integer read FElementSize;
  51.     property Delta: Integer read FDelta;
  52.   end;
  53.  
  54. function EncodeString(const S: String; Buffer: PChar): Integer;
  55. function DecodeString(var S: String; P: PChar): PChar;
  56. function EncodeSymbolOfs(Buffer: PChar; OfsDelta: Integer): Integer;
  57. function DecodeSymbolOfs(Buffer: PChar; var Ofs: Integer): PChar;
  58. function EncodeLineNumber(Buffer: PChar; LineDelta, OfsDelta: Integer): Integer;
  59. function DecodeLineNumber(Buffer: PChar; var LineDelta,OfsDelta: Integer; var FileName: String): PChar;
  60.  
  61. function ParseHex(const S: String; var Index: Integer): Longint;
  62. function ParseDec(const S: String; var Index: Integer): Longint;
  63. function ParseStr(const S: String; var Index: Integer): String;
  64. function ParseChr(const S: String; var Index: Integer): Char;
  65. procedure SkipBlanks(const S: String; var Index: Integer);
  66.  
  67. implementation
  68.  
  69. constructor TGrowingArray.Create(ALimit,ADelta,AElementSize: Integer);
  70. begin
  71.   FElementSize := AElementSize;
  72.   FLimit := ALimit;
  73.   FDelta := ADelta;
  74.   GetMem(FArrPtr, Limit * ElementSize);
  75.   FCurPtr := FArrPtr;
  76. end;
  77.  
  78. destructor TGrowingArray.Destroy;
  79. begin
  80.   FreeMem(FArrPtr, FLimit * FElementSize);
  81.   inherited Destroy;
  82. end;
  83.  
  84. function TGrowingArray.Add: Pointer;
  85. begin
  86.   if Count = Limit then
  87.     Limit := Limit + Delta;
  88.   Result := FCurPtr;
  89.   Inc(PChar(FCurPtr), FElementSize);
  90.   Inc(FCount);
  91. end;
  92.  
  93. function TGrowingArray.Allocate(No: Integer): Pointer;
  94. begin
  95.   if Count + No >= Limit then
  96.     Limit := Count + No + Delta;
  97.   Result := FCurPtr;
  98.   if FElementSize = 1 then
  99.     Inc(PChar(FCurPtr), No)     // Do not use multiplication
  100.   else
  101.     Inc(PChar(FCurPtr), FElementSize * No);
  102.   Inc(FCount, No);
  103. end;
  104.  
  105. procedure TGrowingArray.SetLimit(NewLimit: Integer);
  106. var
  107.   Allocated: Integer;
  108. begin
  109.   Allocated := PChar(FCurPtr) - PChar(FArrPtr);
  110.   ReallocMem(FArrPtr, NewLimit * ElementSize);
  111.   FLimit := NewLimit;
  112.   FCurPtr := PChar(FArrPtr) + Allocated;
  113. end;
  114.  
  115. function TGrowingArray.GetItem(Index: Integer): Pointer;
  116. begin
  117.   Result := PChar(FArrPtr) + Index * ElementSize;
  118. end;
  119.  
  120. function EncodeString(const S: String; Buffer: PChar): Integer;
  121. var
  122.   I: Integer;
  123.   P: PChar;
  124. begin
  125.   P := Buffer;
  126.   PByte(P)^ := Length(S);
  127.   Inc(P);
  128.   I := 0;
  129.   while I < Length(S) do
  130.   begin
  131.     Inc(I);
  132.     P^ := Chr(Ord(S[I]) xor (xorMask + I));
  133.     Inc(P);
  134.   end;
  135.   Result := P - Buffer;
  136. end;
  137.  
  138. function DecodeString(var S: String; P: PChar): PChar;
  139. var
  140.   I: Integer;
  141. begin
  142.   SetString(S, nil, Ord(P^));
  143.   Inc(P);
  144.   I := 0;
  145.   while I < Length(S) do
  146.   begin
  147.     Inc(I);
  148.     S[I] := Chr(Ord(P^) xor (xorMask + I));
  149.     Inc(P);
  150.   end;
  151.   Result := P;
  152. end;
  153.  
  154. function EncodeSymbolOfs(Buffer: PChar; OfsDelta: Integer): Integer;
  155. var
  156.   P: PChar;
  157. begin
  158.   P := Buffer;
  159.   if OfsDelta <= 127 then
  160.     begin
  161.       PByte(P)^ := OfsDelta;
  162.       Inc(P);
  163.     end
  164.   else
  165.     if OfsDelta < 32767 then
  166.       begin
  167.         PWord(P)^ := Lo(OfsDelta) shl 8 + Hi(OfsDelta) + $80;
  168.         Inc(P, 2);
  169.       end
  170.     else
  171.       begin
  172.         PWord(P)^ := $FFFF;
  173.         Inc(P, 2);
  174.         PDWord(P)^ := OfsDelta;
  175.         Inc(P, 4);
  176.       end;
  177.   Result := P - Buffer;
  178. end;
  179.  
  180. function DecodeSymbolOfs(Buffer: PChar; var Ofs: Integer): PChar;
  181. var
  182.   P: PChar;
  183. begin
  184.   P := Buffer;
  185.   if PByte(P)^ <= 127 then
  186.     begin
  187.       Ofs := PByte(P)^;
  188.       Inc(P);
  189.     end
  190.   else
  191.     if PWord(P)^ <> $FFFF then
  192.       begin
  193.         Ofs := PByte(P+1)^ + (PByte(P)^ and $7F) shl 8;
  194.         Inc(P, 2);
  195.       end
  196.     else
  197.       begin
  198.         Inc(P, 2);
  199.         Ofs := PDWord(P)^;
  200.         Inc(P, 4);
  201.       end;
  202.   Result := P;
  203. end;
  204.  
  205. function EncodeLineNumber(Buffer: PChar; LineDelta, OfsDelta: Integer): Integer;
  206. var
  207.   P: PChar;
  208. begin
  209.   P := Buffer;
  210.   if (LineDelta >= 1) and (LineDelta <= 4) and
  211.     (OfsDelta > 0) and (OfsDelta <= escFirst) then
  212.     begin
  213.       PByte(P)^ := (LineDelta - 1) shl escLineShift + OfsDelta - 1;
  214.       Inc(P);
  215.     end
  216.   else
  217.     if (LineDelta <= 127) and (LineDelta >= -128) and
  218.       (OfsDelta <= 127) and (OfsDelta >= -128) then
  219.       begin
  220.         PByte(P)^ := escByteLineByteOfs;
  221.         Inc(P);
  222.         PByte(P)^ := LineDelta;
  223.         Inc(P);
  224.         PByte(P)^ := OfsDelta;
  225.         Inc(P);
  226.       end
  227.     else
  228.       if (LineDelta <= 32767) and (LineDelta >= -32768) and
  229.         (OfsDelta <= 32767) and (OfsDelta >= -32768) then
  230.         begin
  231.           PByte(P)^ := escWordLineWordOfs;
  232.           Inc(P);
  233.           PWord(P)^ := LineDelta;
  234.           Inc(P, 2);
  235.           PWord(P)^ := OfsDelta;
  236.           Inc(P, 2);
  237.         end
  238.       else
  239.         begin
  240.           PByte(P)^ := escWordLineDWordOfs;
  241.           Inc(P);
  242.           PWord(P)^ := LineDelta;
  243.           Inc(P, 2);
  244.           PDWord(P)^ := OfsDelta;
  245.           Inc(P, 4);
  246.         end;
  247.   Result := P - Buffer;
  248. end;
  249.  
  250. function DecodeLineNumber(Buffer: PChar; var LineDelta,OfsDelta: Integer; var FileName: String): PChar;
  251. var
  252.   P: PChar;
  253. begin
  254.   P := Buffer;
  255.   case Ord(P^) and escMask of
  256.     escFileName:
  257.       begin
  258.         Inc(P);
  259.         P := DecodeString(FileName, P);
  260.         LineDelta := MaxInt;
  261.       end;
  262.     escByteLineByteOfs:
  263.       begin
  264.         Inc(P);
  265.         LineDelta := PShortInt(P)^;
  266.         Inc(P);
  267.         OfsDelta := PShortInt(P)^;
  268.         Inc(P);
  269.       end;
  270.     escWordLineWordOfs:
  271.       begin
  272.         Inc(P);
  273.         LineDelta := PSmallInt(P)^;
  274.         Inc(P, 2);
  275.         OfsDelta := PSmallInt(P)^;
  276.         Inc(P, 2);
  277.       end;
  278.     escWordLineDWordOfs:
  279.       begin
  280.         Inc(P);
  281.         LineDelta := PSmallInt(P)^;
  282.         Inc(P, 2);
  283.         OfsDelta := PLongint(P)^;
  284.         Inc(P, 4);
  285.       end;
  286.     else
  287.       LineDelta := (Ord(P^) shr escLineShift) + 1;
  288.       OfsDelta  := (Ord(P^) and escMask) + 1;
  289.       Inc(P);
  290.   end;
  291.   Result := P;
  292. end;
  293.  
  294. function ParseHex(const S: String; var Index: Integer): Longint;
  295. var
  296.   C: Char;
  297.   I: Integer;
  298. begin
  299.   Result := -1;
  300.   I:=0;
  301.   while Index <= Length(S) do
  302.   begin
  303.     C := S[Index];
  304.     case C of
  305.       '0'..'9': I := Ord(C) - Ord('0');
  306.       'A'..'F': I := Ord(C) - (Ord('A') - 10);
  307.       else Exit;
  308.     end;
  309.     if Result = -1 then
  310.       Result := I
  311.     else
  312.       Result := Result shl 4 + I;
  313.     Inc(Index);
  314.   end;
  315. end;
  316.  
  317. function ParseDec(const S: String; var Index: Integer): Longint;
  318. var
  319.   C: Char;
  320.   I: Integer;
  321. begin
  322.   Result := -1;
  323.   I:=0;
  324.   while Index <= Length(S) do
  325.   begin
  326.     C := S[Index];
  327.     case C of
  328.       '0'..'9': I := Ord(C) - Ord('0');
  329.       else Exit;
  330.     end;
  331.     if Result = -1 then
  332.       Result := I
  333.     else
  334.       Result := Result * 10 + I;
  335.     Inc(Index);
  336.   end;
  337. end;
  338.  
  339. function ParseStr(const S: String; var Index: Integer): String;
  340. begin
  341.   Result := '';
  342.   while (Index <= Length(S)) and not (S[Index] in [#9, ' ', '(', ')']) do
  343.   begin
  344.     Result := Result + S[Index];
  345.     Inc(Index);
  346.   end;
  347. end;
  348.  
  349. function ParseChr(const S: String; var Index: Integer): Char;
  350. begin
  351.   Result := #0;
  352.   if Index <= Length(S) then
  353.   begin
  354.     Result := S[Index];
  355.     Inc(Index);
  356.   end;
  357. end;
  358.  
  359. procedure SkipBlanks(const S: String; var Index: Integer);
  360. begin
  361.   while (Index <= Length(S)) and (S[Index] in [#9, ' ']) do
  362.     Inc(Index);
  363. end;
  364.  
  365. end.
  366.